﻿using System;
using System.Collections.ObjectModel;
using System.Collections.Specialized;
using System.ComponentModel;



namespace ScriptEase
{
    public class ObservableCollectionWithItemNotify<T> : ObservableCollection<T> where T : INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler ItemPropertyChanged;
        public event CollectionUpdateEventHandler CollectionUpdate;
      


        protected ObservableCollectionWithItemNotify()
        {
            base.CollectionChanged += itemsCollectionChanged;
        }



        public void BeginUpdate()
        {
            onCollectionUpdate(new CollectionUpdateEventHandlerArgs(CollectionUpdateAction.BeginUpdate));
        }



        public void EndUpdate()
        {
            onCollectionUpdate(new CollectionUpdateEventHandlerArgs(CollectionUpdateAction.EndUpdate));
        }



        private void onCollectionUpdate(CollectionUpdateEventHandlerArgs e)
        {
            if (this.CollectionUpdate != null) this.CollectionUpdate(this, e);
        }



        private void itemsCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
        {
            switch (e.Action)
            {
                case NotifyCollectionChangedAction.Remove: // One or more items were removed from the collection.
                    if (e.OldItems != null)
                        foreach (INotifyPropertyChanged item in e.OldItems)
                            item.PropertyChanged -= onItemPropertyChanged;
                    break;
                case NotifyCollectionChangedAction.Add: // One or more items were added to the collection.
                    if (e.NewItems != null)
                        foreach (INotifyPropertyChanged item in e.NewItems)
                            item.PropertyChanged += onItemPropertyChanged;
                    break;

                case NotifyCollectionChangedAction.Reset: // The content of the collection changed dramatically.
                    // this.Items == Empty, NewItem = null, OldItem = null
                    break;

                default:
                    throw new ArgumentOutOfRangeException();
            }
        }



        private void onItemPropertyChanged(object sender, PropertyChangedEventArgs e)
        {
            if (null != this.ItemPropertyChanged)
                this.ItemPropertyChanged(sender, e);
        }
    }

    public delegate void CollectionUpdateEventHandler(object sender, CollectionUpdateEventHandlerArgs e);

    public enum CollectionUpdateAction
    {
        BeginUpdate,
        EndUpdate
    }

    public class CollectionUpdateEventHandlerArgs : EventArgs
    {
        public CollectionUpdateAction Action { get; private set; }



        public CollectionUpdateEventHandlerArgs(CollectionUpdateAction action)
        {
            this.Action = action;
        }
    }
}